#include "winPlayer.h"

//=======================================================================
// WinAmp
//=======================================================================

bool CWinAmpPlayer::IsOpen()
{
	HWND hwnd = ::FindWindow(L"Winamp v1.x", NULL);
	return hwnd != NULL;
}

int CWinAmpPlayer::GetCurrentTime()
{
	HWND hwnd = ::FindWindow(L"Winamp v1.x", NULL);
	if(hwnd == NULL)
	{
		return -1;
	}

	return (int)::SendMessage(hwnd,WM_USER,0,105);
}

std::string CWinAmpPlayer::GetMediaTitle()
{
	HWND hwnd = ::FindWindow(L"Winamp v1.x", NULL);
	if(hwnd == NULL)
	{
		return "";
	}

	std::string res;
	char name[MAX_PATH];
	GetWindowTextA(hwnd, name, MAX_PATH);

	res = name;
	std::string::size_type begin = res.find(' ');
	std::string::size_type end = res.rfind(" - Winamp");
	++begin;

	return res.substr(begin, end - begin);
}

////=======================================================================
//// iTunes
////=======================================================================
//
//CITunesPlayer::CITunesPlayer()
//{
//	m_isInited = false;
//	m_dwRefCount=0;
//
//	ITypeLib* pITypeLib = NULL ;
//	HRESULT	 hr = ::LoadRegTypeLib(LIBID_iTunesLib, 
//		1, 5, // Major/Minor version numbers
//		0x00, 
//		&pITypeLib) ;
//	// Get type information for the interface of the object.
//	hr = pITypeLib->GetTypeInfoOfGuid(DIID__IiTunesEvents, &m_pITypeInfo);
//
//	pITypeLib->Release() ;
//}
//
//CITunesPlayer::~CITunesPlayer()
//{
//	OniTunesClose();
//}
//
//bool CITunesPlayer::init()
//{
//	HRESULT hr = S_OK;
//	if (!m_spITunes)
//	{
//		
//		hr = m_spITunes.CoCreateInstance(CLSID_iTunesApp, NULL, CLSCTX_LOCAL_SERVER);
//		MessageBoxA(NULL, "CoCreateInstance", "CoCreateInstance", MB_OK);
//	}
//	if (hr == S_OK)
//	{
//		IConnectionPointContainer  * pCPC;
//
//		hr=m_spITunes->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC);
//
//		IConnectionPoint * pCP;
//
//		//_IiTunesEvents * pITEvent;
//		hr=pCPC->FindConnectionPoint (DIID__IiTunesEvents, &pCP);
//		pCPC->Release();
//
//		DWORD dwAdvise;
//		hr = pCP->Advise(this,&dwAdvise);
//		MessageBoxA(NULL, "hr = pCP->Advise(this,&dwAdvise);", "hr = pCP->Advise(this,&dwAdvise);", MB_OK);
//	}
//
//	return true;
//}
//
//void CITunesPlayer::OniTunesClose()
//{
//	if(m_spITunes)
//	{
//		m_spITunes.Release();
//		m_spITunes = NULL;
//	}
//	m_isInited = false;
//}
//
//bool CITunesPlayer::IsOpen()
//{
//	if (::FindWindow(L"iTunes", NULL) == NULL)
//		return false;
//	IRunningObjectTable*	rot;
//	HRESULT hr = ::GetRunningObjectTable(0, &rot);
//	IMoniker* moniker = NULL;
//	IEnumMoniker* enumMoniker;
//
//	CLSID clsid;
//	IBindCtx* binder; 
//	hr = ::CreateBindCtx(0, &binder);
//	BSTR displayName; 
//
//	hr = rot->EnumRunning( &enumMoniker ); 
//	hr = enumMoniker->Next( 1, &moniker, NULL );
//	while( hr == S_OK )
//	{
//		moniker->GetClassID( &clsid );
//		moniker->GetDisplayName( binder, NULL, &displayName );
//		if (CComBSTR(displayName) == "clsid:BBEB08F8-9126-4E20-AAD3-70B470144C7E:")
//		{
//			if (!m_isInited)
//			{
//				init();
//				m_isInited = true;
//			}
//			return true;
//		}
//		hr = enumMoniker->Next( 1, &moniker, NULL );
//	}
//	return 0;
//
//}
//
//std::string CITunesPlayer::GetMediaTitle()
//{
//	if (!IsOpen())
//	{
//		return "";
//	}
//
//	CComPtr<IITTrack> spTrack;
//
//	HRESULT hr = m_spITunes->get_CurrentTrack(&spTrack);
//
//	CComBSTR songName, songArtist;
//	spTrack->get_Artist(&songArtist);
//	CW2A artist(songArtist);
//
//	std::string res = artist;
//
//	spTrack->get_Name(&songName);
//	CW2A name(songName);
//
//	res += std::string(" - ") + (char*)name;
//
//
//	return res;
//
//}
//
//int CITunesPlayer::GetCurrentTime()
//{
//	if (!IsOpen())
//	{
//		return -1;
//	}
//
//	CComPtr<IITTrack> spTrack;
//	HRESULT hr = m_spITunes->get_CurrentTrack(&spTrack);
//
//	long time;
//	m_spITunes->get_PlayerPosition(&time);
//
//	return time * 1000;
//}
//
//ULONG STDMETHODCALLTYPE CITunesPlayer::AddRef()
//{
//	InterlockedIncrement(&m_dwRefCount);
//	return m_dwRefCount;
//}
//ULONG STDMETHODCALLTYPE CITunesPlayer::Release()
//{
//	InterlockedDecrement(&m_dwRefCount);
//	if (m_dwRefCount == 0)
//	{
//		delete this;
//		return 0;
//	}
//	return m_dwRefCount;
//}
//HRESULT STDMETHODCALLTYPE CITunesPlayer::QueryInterface(REFIID iid, void **ppvObject)
//{
//	if( (iid == IID_IDispatch) || (iid == DIID__IiTunesEvents) )
//	{
//		m_dwRefCount++;
//		*ppvObject = this;//(_IiTunesEvents *)this;
//		return S_OK;
//	}
//	if (iid == IID_IUnknown)
//	{
//		m_dwRefCount++;            
//		*ppvObject = this;//(IUnknown *)this;
//		return S_OK;
//	}
//	return E_NOINTERFACE;
//}
//HRESULT STDMETHODCALLTYPE CITunesPlayer::GetTypeInfoCount(UINT* pctinfo)
//{
//	return E_NOTIMPL;
//}
//HRESULT STDMETHODCALLTYPE CITunesPlayer::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
//{
//	return E_NOTIMPL;
//}
//HRESULT __stdcall CITunesPlayer::GetIDsOfNames(const IID& iid,    OLECHAR** arrayNames, UINT countNames,
//															 LCID, 
//															 DISPID* arrayDispIDs)
//{
//	if(iid != IID_NULL) {
//		return DISP_E_UNKNOWNINTERFACE ;
//	}
//	HRESULT hr = m_pITypeInfo->GetIDsOfNames(arrayNames, countNames, arrayDispIDs) ;
//	return hr;
//}
//HRESULT STDMETHODCALLTYPE CITunesPlayer::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
//															  WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
//															  EXCEPINFO* pexcepinfo, UINT* puArgErr)
//{
//	if (dispidMember == 9)
//	{
//		OniTunesClose();
//	}
//
//	return S_OK;
//}

//=======================================================================
// Windows Media Player
//=======================================================================


/////////////////////////////////////////////////////////////////////////////
// CRemoteHost

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CWmpPlayer::CRemoteHost::CRemoteHost()
{

}

CWmpPlayer::CRemoteHost::~CRemoteHost()
{

}

//***************************************************************************
// QueryService()
// API from IServiceProvider
//***************************************************************************
HRESULT CWmpPlayer::CRemoteHost::QueryService(REFGUID guidService, REFIID riid, void ** ppv)
{
	return ppv? QueryInterface(riid, ppv) : E_POINTER;
}


//***************************************************************************
// GetServiceType()
// Always return Remote so that the player OCX runs at remote state
//***************************************************************************
HRESULT CWmpPlayer::CRemoteHost::GetServiceType(BSTR * pbstrType)
{
	HRESULT hr = E_POINTER;
	if(pbstrType)
	{
		*pbstrType = ::SysAllocString(L"Remote");
		hr = *pbstrType? S_OK : E_POINTER;
	}
	return hr;
}

//***************************************************************************
// GetApplicationName()
// Return the application name. It will be shown in player's menu View >
// Switch to applications
//***************************************************************************
HRESULT CWmpPlayer::CRemoteHost::GetApplicationName(BSTR * pbstrName)
{
	HRESULT     hr = E_POINTER;
	if(pbstrName)
	{
		CComBSTR    bstrAppName = _T("OnlyLyric");
		*pbstrName = bstrAppName.Detach();
		hr = *pbstrName? S_OK : E_POINTER;
	}
	return hr;
}

//***************************************************************************
// GetScriptableObject()
// There is no scriptable object in this application
//***************************************************************************
HRESULT CWmpPlayer::CRemoteHost::GetScriptableObject(BSTR * pbstrName, IDispatch ** ppDispatch)
{
	if(pbstrName)
	{
		*pbstrName = NULL;
	}
	if(ppDispatch)
	{
		*ppDispatch = NULL;
	}
	return E_NOTIMPL;
}

//***************************************************************************
// GetCustomUIMode()
// When UI mode of the player OCX is set to custom, this function is called
// to give the skin file path that will be loaded to the player OCX.
// 
//***************************************************************************
HRESULT CWmpPlayer::CRemoteHost::GetCustomUIMode(BSTR * pbstrFile)
{
	HRESULT     hr = E_POINTER;
	return hr;
}

CWmpPlayer::CWmpPlayer()
{
	m_pView = 0;
	m_hwnd = 0;
	_Module.Init(NULL, NULL, &LIBID_ATLLib);

	CreateWnd();
	InitRemotePlayer();
}

CWmpPlayer::~CWmpPlayer()
{
	if (m_spPlayer)
		m_spPlayer.Release();
	if (m_pView)
		m_pView->DestroyWindow();
	delete m_pView;
	if (m_hwnd)
		::DestroyWindow(m_hwnd);
	_Module.Term();
}

bool CWmpPlayer::CreateWnd()
{

	// Create windows class
	WNDCLASS wndclass;
	memset(&wndclass, 0, sizeof WNDCLASS);
	wndclass.lpfnWndProc = DefWindowProc;
	wndclass.lpszClassName = L"OnlyLyric-wmp";

	static bool isRegistered = false;
	if (isRegistered == false)
	{
		if (RegisterClass(&wndclass) == 0)
		{
			return false;
		}
	}
	isRegistered = true;

	// Create a window.
	if ((m_hwnd = CreateWindow(
		L"OnlyLyric-wmp",
		L"OnlyLyric-wmp",
		WS_OVERLAPPEDWINDOW | WS_DISABLED,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		NULL,
		NULL)) == NULL)
	{
		return false;
	}

	return true;
}

bool CWmpPlayer::InitRemotePlayer()
{

	HRESULT                             hr = S_OK;
	CComPtr<IObjectWithSite>            spHostObject;
	CComPtr<IAxWinHostWindow>           spHost;
	CComObject<CRemoteHost>             *pRemoteHost;
	m_pView = new CAxWindow();
	if(!m_pView)
	{
		hr = E_OUTOFMEMORY;
	}

	if(SUCCEEDED(hr)) 
	{
		m_pView->Create(m_hwnd, NULL, NULL, WS_CHILD | WS_DISABLED);
		if(::IsWindow(m_pView->m_hWnd))
		{
			hr = m_pView->QueryHost(IID_IObjectWithSite, (void **)&spHostObject);
			if(!spHostObject.p)
			{
				hr = E_POINTER;
			}
		}
	}

	// Create remote host which implements IServiceProvider and IWMPRemoteMediaServices
	if(SUCCEEDED(hr))
	{
		hr = CComObject<CRemoteHost>::CreateInstance(&pRemoteHost);
		if(pRemoteHost)
		{
			pRemoteHost->AddRef();
		}
		else
		{
			hr = E_POINTER;
		}
	}

	// Set site to the remote host
	if(SUCCEEDED(hr))
	{
		hr = spHostObject->SetSite((IWMPRemoteMediaServices *)pRemoteHost);
	}

	if(SUCCEEDED(hr))
	{
		hr = m_pView->QueryHost(&spHost);
		if(!spHost.p)
		{
			hr = E_NOINTERFACE;
		}
	}

	// Create WMP Control here
	if(SUCCEEDED(hr))
	{
		hr = spHost->CreateControl(CComBSTR(L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"), m_pView->m_hWnd, NULL);
	}
	if(SUCCEEDED(hr))
	{
		hr = m_pView->QueryControl(&m_spPlayer);
		if(!m_spPlayer.p)
		{
			hr = E_NOINTERFACE;
		}
	}
	// Release remote host object
	if(pRemoteHost)
	{
		pRemoteHost->Release();
	}

	return true;
}

bool CWmpPlayer::IsOpen()
{
	HRESULT res = E_POINTER;
	VARIANT_BOOL state = FALSE;
	CComPtr<IWMPPlayerApplication>  spPlayerApp;

	if (m_spPlayer.p)
		res = m_spPlayer->get_playerApplication(&spPlayerApp);
	if (SUCCEEDED(res))
		res = spPlayerApp->get_playerDocked(&state);
	if (SUCCEEDED(res) && state == VARIANT_FALSE)
		return true;
	else
	{
		Stop();
		return false;
	}
}

std::string CWmpPlayer::GetMediaTitle()
{
	USES_CONVERSION;

	CComPtr<IWMPMedia>   spMedia;

	if(m_spPlayer.p)
		m_spPlayer->get_currentMedia(&spMedia);
	if(spMedia.p)
	{
		CComBSTR artist, title;
		spMedia->getItemInfo(CComBSTR("Artist"), &artist);
		spMedia->getItemInfo(CComBSTR("Title"), &title);

		artist += " - ";
		artist += title;
		char *pstr = W2A(artist);
		return pstr;
	}
	
	return "";
}

int CWmpPlayer::GetCurrentTime()
{
	HRESULT hRes;
	double res = -1;
	CComPtr<IWMPControls>   spControls;

	if(m_spPlayer.p)
		m_spPlayer->get_controls(&spControls);
	if(spControls.p )
		hRes = spControls->get_currentPosition(&res);

	return (int) res * 1000;		// convert second to ms
}

int CWmpPlayer::Stop() 
{
	HRESULT res = NULL;
	CComPtr<IWMPControls>   spControls;
	CComPtr<IWMPCore> spCore;

	if(m_spPlayer.p)
		m_spPlayer->get_controls(&spControls);
	if(spControls.p)
		res = spControls->stop();

	if (m_spPlayer.p)
		m_spPlayer->close();

	return (int) res;
}